// I/O => wait + copy
#include <iostream>
#include <cstring>
#include <cerrno>
#include <algorithm>
#include <vector>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <poll.h>

// global variable
static const int max_capacity = 1024;
static int fds_index = 0;

// container
pollfd fds[max_capacity];

// socket
static int get_socket_fd()
{
    // socket
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd < 0)
    {
        std::cerr << strerror(errno) << std::endl;
        exit(1);
    }
    // info
    sockaddr_in my_addr;
    bzero(&my_addr, sizeof(sockaddr_in));
    my_addr.sin_family = AF_INET;
    my_addr.sin_addr.s_addr = INADDR_ANY;
    my_addr.sin_port = htons(8083);
    // bind
    if (bind(socket_fd, (sockaddr *)&my_addr, sizeof(sockaddr_in)) == -1)
    {
        std::cerr << strerror(errno) << std::endl;
        exit(2);
    }
    return socket_fd;
}

// handler
static bool accept_handler(const int listen_fd)
{
    sockaddr_in peer_addrin;
    socklen_t addr_len = sizeof(sockaddr_in);
    int new_fd = accept(listen_fd, (sockaddr *)&peer_addrin, &addr_len);
    if (new_fd < 0)
    {
        std::cerr << strerror(errno) << std::endl;
        exit(3);
    }
    if (fds_index == max_capacity)
    {
        close(new_fd);
        return false;
    }
    fds[fds_index].revents &= 0;
    fds[fds_index].events |= POLLIN;
    fds[fds_index++].fd = new_fd;
    return true;
}
static bool read_copy_handler(const int socket_fd)
{
    const int buffer_size = 1024;
    char buffer[buffer_size];
    bzero(buffer, buffer_size);
    ssize_t read_size = read(socket_fd, buffer, buffer_size);
    if (read_size == 0)
    {
        return false;
    }
    std::cout << std::string(buffer);
    return true;
}
// other handler
//...
//  main
int main()
{
    int listen_fd = get_socket_fd();
    fds[fds_index].fd = listen_fd;
    fds[fds_index].events |= POLLIN;
    fds[fds_index++].revents &= 0;
    listen(listen_fd, 5);
    while (true)
    {
        // set time to wait
        const static int timeout = 5000;
        // poll
        int ready_num = poll(fds, fds_index, timeout);
        std::cout << ready_num << std::endl;
        if (ready_num == 0)
        {
            // other work...
            continue;
        }
        if (ready_num < 0)
        {
            // error
            std::cerr << strerror(errno) << std::endl;
            exit(3);
        }
        else
        {
            // event
            if (fds[0].revents & POLLIN)
            {
                accept_handler(fds[0].fd);
            }
            for (int i = 1; i < fds_index; i++)
            {
                if (fds[i].revents & POLLIN)
                    if (!read_copy_handler(fds[i].fd))
                    {
                        fds[i].fd = -1;
                    }
            }
        }
    }
    close(listen_fd);
    return 0;
}